package com.example.demo;

import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.statement.PreparedStatementHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.*;
import org.apache.ibatis.parsing.GenericTokenParser;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.SQLException;

@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
@Component
public class XcMybatisPlusInnerInterceptor implements InnerInterceptor {
    private final static String START_TOKEN = "@{";
    private  final static String END_TOKEN = "}";

    @Override
    public boolean willDoQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {

        // 查询时，重置 sql 语句
        GenericTokenParser parser = new GenericTokenParser(START_TOKEN, END_TOKEN, content -> {
            MapperMethod.ParamMap parameter1 = (MapperMethod.ParamMap) parameter;
            Object value = parameter1.get(content);
            if(value != null && value instanceof String){
                return (String)value;
            }
            return START_TOKEN +content+ END_TOKEN;
        });
        String sql = boundSql.getSql();
        String parseSql = parser.parse(sql);
        Field field = null;
        try {
            field = boundSql.getClass().getDeclaredField("sql");
            field.setAccessible(true);
            field.set(boundSql, parseSql);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        return true;
    }

}
